import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosResponse
} from 'axios'
import { Message } from 'element-ui'
import { refreshToken } from './../services/front/index'
import { getCookies, setCookies } from '@/utils/cookie'
import { ACCESS_TOKEN, REFRESH_TOKEN } from '@/utils/constants'
import { getFormDataParams } from '@/utils/common'
import router from '@/router'

let refreshing = false
const requests: Array<any> = []
export default class Request {
  private instance: AxiosInstance

  constructor (baseURL: string) {
    this.instance = axios.create({
      baseURL
    })

    this.instance.interceptors.request.use((config: AxiosRequestConfig) => {
      const token = getCookies(ACCESS_TOKEN) as string
      (config.headers as AxiosRequestHeaders).Authorization = token
      return config
    })

    this.instance.interceptors.response.use((response: AxiosResponse) => {
      return response.data
    }, async (error) => {
      if (error.response) {
        const { status } = error.response
        if (status === 400) {
          Message.error('请求参数错误')
        } else if (status === 401) {
          // token 无效 （没有提供 token, token 是无效的, token 过期了）
          // 如果有 refresh_token 则尝试使用 refresh_token 获取新的 ACCESS_TOKEN
          const refreshtoken = getCookies(REFRESH_TOKEN)
          if (!refreshing) {
            refreshing = true
            return refreshToken(getFormDataParams({ refreshtoken })).then((data: any) => {
              const content = JSON.parse(data.content)
              setCookies(ACCESS_TOKEN, content.access_token)
              setCookies(REFRESH_TOKEN, content.refresh_token)

              requests.forEach(cb => cb())
              requests.splice(0)
            }).catch((error: any) => {
              console.error(error)
              router.replace({
                name: 'login'
              })
            }).finally(() => {
              refreshing = false
            })
          }

          return new Promise((resolve) => {
            requests.push(() => {
              resolve(this.request(error.config))
            })
          })
        } else if (status === 403) {
          Message.error('没有权限，请联系管理员')
        } else if (status === 404) {
          Message.error('请求资源不存在')
        } else if (status >= 500) {
          Message.error('服务端错误，请联系管理员')
        }
      } else if (error.request) { // 请求发出去了，但是没有收到响应（请求超时，网络断开）
        Message.error('请求超时，请刷新重试')
      } else { // 在设置请求时发生了一些事情，触发了一个错误
        Message.error('请求失败: ' + error.message)
      }
      // 把请求失败的错误对象继续抛出，扔给下一个调用者
      return Promise.reject(error)
    })
  }

  public request (config: AxiosRequestConfig): Promise<AxiosResponse> {
    return this.instance.request(config)
  }
}
